/**
 * 
 */
package neptune.manager.validator;

import java.util.ArrayList;

/**
 * Questa classe estende una {@link ValidatorRule} per contemplare la
 * possibilita' di valutare piu' rule in sequenza. E' infatti possibile
 * registrare delle ValidatorRule a questa classe, che saranno interpellate
 * anch'esse ad una chiamata di
 * {@link Validator#validate(Object, ValidatorResult)} su questa classe.<br>
 * <br>
 * Poiche' il Validator deve essere tipizzato (fa uso di generics), anche le
 * rule ad esso associate devono essere tipizzate con lo stesso tipo. In altre
 * parole, il metodo validate del Validator e quello delle ValidatorRule ad esso
 * associate, devono operare sullo stesso tipo di parametro.
 * 
 * @author Roberto Bifulco [RobertoBifulco.it] [info@robertoBifulco.it]
 * 
 */
public abstract class Validator<T> extends ValidatorRule<T> {

	/**
	 * Gli stati che puo' assumere il risultato della validazione
	 * 
	 * @author Roberto Bifulco [RobertoBifulco.it] [info@robertoBifulco.it]
	 *
	 */
	public static enum Status {
		VALID, ERROR;
	}

	private ArrayList<ValidatorRule<T>> rules = new ArrayList<ValidatorRule<T>>(0);

	/**
	 * Aggiunge una regola a questo validator
	 * 
	 * @param rule
	 */
	public void addRule(ValidatorRule<T> rule) {
		rules.add(rule);
	}

	/**
	 * Rimuove una regola da questo validator
	 * 
	 * @param rule
	 */
	public void removeRule(ValidatorRule<T> rule) {
		rules.remove(rule);
	}

	/**
	 * Rimuove tutte le regole definite sul validator
	 * 
	 */
	public void clearRules() {
		rules.clear();
	}

	/**
	 * Sovrascrive il metodo
	 * {@link ValidatorRule#validate(Object, ValidatorResult)} per contemplare
	 * la valutazione delle ValidatorRule registrate a questo Validator.
	 * 
	 */
	@Override
	public ValidatorResult validate(T toValidate, ValidatorResult result) {
		if (result == null)
			result = new ValidatorResult("Validator");

		ValidatorResult childResult = result.createChild(getName());
		validationAlgorithm(toValidate, childResult);

		for (ValidatorRule<T> rule : rules) {
			rule.validate(toValidate, childResult);
		}

		return result;
	}
}
